import type { Attrs, MarkType, Schema } from "./schema.ts";
import { compareDeep } from "./comparedeep.ts";
import { immerable } from "immer";
/**
 * 基础标记实现 例如颜色 背景色 批注
 */
export class Mark {
  [immerable] = true;
  type: MarkType;
  attrs: Attrs;
  constructor(
    type: MarkType,
    attrs: Attrs,
  ) {
    this.type = type;
    this.attrs = attrs;
  }
  // 判断两个标记是否相等
  eq(other: Mark): boolean {
    return this == other ||
      (this.type == other.type && compareDeep(this.attrs, other.attrs));
  }
  //判断一个标记是否在另一个标记数组中
  isInSet(set: Mark[]): boolean {
    for (let i = 0; i < set.length; i++) {
      if (this.eq(set[i])) return true;
    }
    return false;
  }
  toJSON(): any {
    const obj: any = { type: this.type.name };
    for (let _ in this.attrs) {
      obj.attrs = this.attrs;
      break;
    }
    return obj;
  }
  static setFrom(marks?: Mark | Mark[] | null): Mark[] {
    if (!marks || Array.isArray(marks) && marks.length == 0) {
      return Mark.none;
    }
    if (marks instanceof Mark) return [marks];
    if (Array.isArray(marks)) {
      const copy = marks.slice();
      copy.sort((a, b) => a.type.rank - b.type.rank);
      return copy;
    }
    return [];
  }
  static sameSet(a: Mark[], b: Mark[]): boolean {
    if (a == b) return true;
    if (a.length != b.length) return false;
    for (let i = 0; i < a.length; i++) {
      if (!markEq(a[i], b[i])) return false;
    }
    return true;
  }
  static fromJSON(schema: Schema, json: any): Mark {
    if (!json) throw new RangeError("Invalid input for Mark.fromJSON");
    let type = schema.marks[json.type];
    if (!type) {
      throw new RangeError(`There is no mark type ${json.type} in this schema`);
    }
    return type.create(json.attrs);
  }
  static none: Mark[] = [];
}
export function markEq(t: Mark, other: Mark): boolean {
  return t == other ||
    (t.type == other.type && compareDeep(t.attrs, other.attrs));
}
